package com.winit.openapi.controller;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.query.Page;
import com.winit.common.query.Searchable;
import com.winit.common.spi.command.GetByKeyCommand;
import com.winit.common.spi.context.CommandContext;
import com.winit.erp.spi.bpartner.BpartnerService;
import com.winit.erp.spi.bpartner.command.BpartnerCommand;
import com.winit.erp.spi.bpartner.vo.Bpartner;
import com.winit.openapi.chinapost.constants.ChinaMsgType;
import com.winit.openapi.chinapost.constants.ChinaPostErrorCode;
import com.winit.openapi.chinapost.constants.ChinaPostMD5Util;
import com.winit.openapi.chinapost.model.RequestObject;
import com.winit.openapi.chinapost.model.Response;
import com.winit.openapi.chinapost.model.ResponseError;
import com.winit.openapi.chinapost.model.ResponseItems;
import com.winit.openapi.chinapost.model.ResponsesObject;
import com.winit.openapi.constants.ApiConstant;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.Config;
import com.winit.openapi.util.RequestUtil;
import com.winit.openapi.util.ValidateUtil;
import com.winit.vms.spi.ConfigService;

/**
 * Controller基类
 * 
 * @version <pre>
 * Author	Version		Date		Changes
 * kang.wang 	1.0  		2014-12-30 	Created
 * 
 * </pre>
 * @since 1.
 */
@Controller
public class BaseController {

    private static final Logger logger    = LoggerFactory.getLogger(BaseController.class);

    public static final String  OPENAPI_SERVICE   = "/service";

    public static final String  ERP_THIRD = "/api";

    public static final String  SUCCESS   = "/success";

    public static final String  ERROR               = "/error";
    
    public static final String  API_ADAPTED_ERROR   = "/api_adapted_error";

    public static final String  API_ADAPTED_SUCCESS = "/api_adapted_success";

    @Resource
    private ConfigService configService;
    
    @Resource
    protected Config                        config;
    
    @Resource
    private BpartnerService bpartnerService;

    @ModelAttribute(ApiConstant.REQUEST_MSG)
    public RequestMsg getRequestMsg(ServletRequest request) {
        RequestMsg requestMsg = RequestUtil.getRequestMsg(request);
        return requestMsg;
    }

    @ModelAttribute(ApiConstant.RESPONSE_MSG)
    public ResponseMsg getResponseMsg(ServletRequest request) {
        ResponseMsg responseMsg = RequestUtil.getResponseMsg(request);
        if (responseMsg == null) {
            responseMsg = new ResponseMsg();
            // 此步骤把responseMsg放入reqeust,便于后续步骤记录日志
            RequestUtil.setResponseMsg(request, responseMsg);
        }
        return responseMsg;
    }
    
    public ResponsesObject getResponsesObject(String errorCode) {
    	ResponsesObject responseMsg = new ResponsesObject();
    	ResponseItems responseItems = new ResponseItems();
    	Response response = new Response();
    	ResponseError responseError = new ResponseError();
    	if(errorCode != null){
    	    responseError.setReason(errorCode);
    	    responseError.setSuccess(false);
    	    responseItems.setResponse(responseError);
    	}else{
    		response.setSuccess(true);
    		responseItems.setResponse(response);
    	}
    	responseMsg.setResponseItems(responseItems);
        return responseMsg;
    }
    
    
    /**
     * 校验传入的参数
     */
    protected void verifyParameters(RequestObject requestObject) {
        if (requestObject != null) {
            if (StringUtils.isBlank(requestObject.getData_digest())
                    || StringUtils.isBlank(requestObject
                            .getLogistic_provider_id())
                    || StringUtils.isBlank(requestObject
                            .getLogistics_interface())
                    || StringUtils.isBlank(requestObject.getMsg_type())) {
                throw new ApiException(ChinaPostErrorCode.ERROR_S12);
            }
        } else {
            throw new ApiException(ChinaPostErrorCode.ERROR_S12);
        }
    }

    /**
     * 验证签名
     */
    protected void verifySignature(RequestObject requestObject) {
    	try
    	{
	    	//获取数据库配置的秘钥
	    	GetByKeyCommand<String> command = new GetByKeyCommand<String>();
	    	command.setSearchKey(ChinaMsgType.CHINAPOST_ACCEPT_ENCRYPTION_KEY);
	    	String chinaKey = configService.getValue(command);
	        //String secretKey = "123";
	        //获取CP发送数字签名
	        String digestKey = requestObject.getData_digest();
	        //获取CP消息内容
	        String interfaceData = requestObject.getLogistics_interface();
	        //进行MD5和BASE64加密
	        String encryptionKey = ChinaPostMD5Util.getMd5AndBase64(interfaceData+chinaKey);
	        //如果密钥不相同,则抛出异常
	        if(!encryptionKey.equals(digestKey))
	        {
	        	logger.info("签名错误：传入的签名：="+digestKey+"; 验签之后的签名 ="+encryptionKey +"; 秘钥是chinaKey="+chinaKey);
	        	throw new ApiException(ChinaPostErrorCode.ERROR_S02);
	        }
    	}
    	catch (Exception e) 
    	{
    		throw new ApiException(ChinaPostErrorCode.ERROR_S02,e);
		}
    }
    
    /**
     * 构建分页参数
     * TODO Add comments here.
     * @param json
     * @return
     */
    protected Searchable buildSearchablePageParams(JSONObject json) {
        int pageNo = ApiConstant.PAGE_NO_DEFAULT;
        int pageSize = ApiConstant.PAGE_SIZE_DEFAULT;
        // pageParams
        if (isExistValue(json, "pageParams")) {
            JSONObject pageParams = json.getJSONObject("pageParams");

            if (ValidateUtil.isIntNumber(pageParams.getString("pageNo"))) {
                pageNo = pageParams.getInteger("pageNo");
                if (pageNo <= 0) {
                    throw new ApiException(ErrorCode.FIELD_ERROR, "pageNo");
                }
            } else if (isExistValue(pageParams, "pageNo") && !ValidateUtil.isIntNumber(pageParams.getString("pageNo"))) {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "pageNo");
            }

            if (ValidateUtil.isIntNumber(pageParams.getString("pageSize"))) {
                pageSize = pageParams.getInteger("pageSize");
                if (pageSize <= 0) {
                    throw new ApiException(ErrorCode.FIELD_ERROR, "pageSize");
                }
            } else if (isExistValue(pageParams, "pageSize")
                       && !ValidateUtil.isIntNumber(pageParams.getString("pageSize"))) {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "pageSize");
            }

        }
        Searchable search = Searchable.newSearchable();
        search.setPage(pageNo, pageSize);
        return search;
    }
    
    /**
     * 构建分页参数
     * TODO Add comments here.
     * @param json
     * @return
     */
    protected Map<String, Integer> buildPageParams(JSONObject json) {
        Map<String, Integer> map = new HashMap<String, Integer>();
        int pageNo = ApiConstant.PAGE_NO_DEFAULT;
        int pageSize = ApiConstant.PAGE_SIZE_DEFAULT;
        // pageParams
        if (isExistValue(json, "pageParams")) {
            JSONObject pageParams = json.getJSONObject("pageParams");

            if (ValidateUtil.isIntNumber(pageParams.getString("pageNo"))) {
                pageNo = pageParams.getInteger("pageNo");
                if (pageNo <= 0) {
                    throw new ApiException(ErrorCode.FIELD_ERROR, "pageNo");
                }
            } else if (isExistValue(pageParams, "pageNo") && !ValidateUtil.isIntNumber(pageParams.getString("pageNo"))) {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "pageNo");
            }

            if (ValidateUtil.isIntNumber(pageParams.getString("pageSize"))) {
                pageSize = pageParams.getInteger("pageSize");
                if (pageSize <= 0) {
                    throw new ApiException(ErrorCode.FIELD_ERROR, "pageSize");
                }
            } else if (isExistValue(pageParams, "pageSize")
                       && !ValidateUtil.isIntNumber(pageParams.getString("pageSize"))) {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "pageSize");
            }

        }
        map.put("pageNo", pageNo);
        map.put("pageSize", pageSize);
        return map;
    }
    
    protected  Map<String, Object> getPageParams(Page pagelist){

        Map<String, Object> pageMap = new HashMap<String, Object>();

        if (pagelist != null && pagelist.getPageable() != null) {
            pageMap.put("pageNo", pagelist.getPageable().getPageNumber());
            pageMap.put("pageSize", pagelist.getPageable().getPageSize());
            pageMap.put("totalCount", pagelist.getTotalElements());
        } else {
            pageMap.put("pageNo", 0);
            pageMap.put("pageSize", 0);
            pageMap.put("totalCount", 0);
        }

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("pageParams", pageMap);
        return data;
    }
    
    // 判断非必填字段是否有值
    public boolean isExistValue(JSONObject jsonObject, String key) {
        if (jsonObject.containsKey(key)) {
            return !"".equals(jsonObject.getString(key).trim());
        }
        return false;
    }
    protected String responseSuccess(){
        return "<responses><responseItems><response><success>true</success></response></responseItems></responses>";
    }
    protected String responseError(String errorCode){
        return "<responses><responseItems><response><success>false</success><reason>"+errorCode+"</reason></response></responseItems></responses>";
    }
    
    /**
     * 获取上下文客户编码
     * @return
     */
    protected String getCurrentCustomerCode() {
        String userId = CommandContext.getContext().getUserId();
        BpartnerCommand bpartnerCommand = new BpartnerCommand();
        bpartnerCommand.setcBpartnerId(Long.valueOf(userId));
        Bpartner bpartner = bpartnerService.queryBpartnerById(bpartnerCommand);
        if (bpartner == null) {
            return null;
        }
        return bpartner.getValue();
    }
}
